import {Channel} from "amqplib";
import {EventEmitter} from "events";
import {PlayerModel, getLevel} from "../database/models/player";
import {GameTypes} from "../match/gameTypes"
import {SimplePlayer} from "../match/IRoom"
import gameHandlers from "./message-handlers-rmq/game";


function toBuffer(json: { name: string, payload: any }): Buffer {
  return new Buffer(JSON.stringify(json))
}

export class PlayerRmqProxy extends EventEmitter implements SimplePlayer {
  model: any;
  channel: Channel;
  ip: any;
  room: any
  seatIndex: number

  readonly myQueue: string
  readonly myRouteKey: string

  constructor(model, channel, readonly gameName: GameTypes) {
    super()
    this.model = model
    this.ip = model.ip;
    this.channel = channel
    this.myQueue = `user:${this._id}`
    this.myRouteKey = `user.${this._id}.${this.gameName}`
  }

  getIpAddress() {
    return this.ip || '8.8.8.8'
  }

  get location() {
    return 'rabbit hole'
  }

  get _id(): string {
    return this.model && this.model._id;
  }

  sendMessage(name: 'room/join-success', message: { _id: string, rule: any });
  sendMessage(name: 'room/join-fail', message: { reason: string });
  sendMessage(name: 'room/leave-success', message: { _id: string });
  sendMessage(name: 'room/leave-fail', message: { _id: string });
  sendMessage(name: 'room/reconnectReply', {errorCode: number, _id: string, rule: any});
  sendMessage(name: never, message: any);
  sendMessage(name: string, message: any);

  sendMessage(name: string, message: any) {
    try {
      this.channel.publish('userCenter', this.myRouteKey, toBuffer({payload: message, name}))
    } catch (e) {
      console.error('playerRmqProxy sendMessage ', name, 'with error', e)
    }
  }

  get level(): number {
    if (this.model) {
      return this.getLevel(this.model)
    }
    return 0
  }

  private getLevel(model): number {
    return getLevel(model)
  }

  async addGold(v) {
    if (this.model) {
      const oldLevel = this.level
      const newModel = await PlayerModel.findByIdAndUpdate(this.model._id, {$inc: {gold: v}}, {'new': true})

      if (newModel.gold < 0) {
        newModel.gold = 0
        await newModel.save()
      }

      if (newModel) {
        const newLevel = this.getLevel(newModel)
        this.sendMessage('resources/updateGold', {gold: newModel.gold, levelUp: oldLevel !== newLevel})
      }
    }
  }


  isRobot(): boolean {
    return false
  }

  getGameMsgHandler() {
    return gameHandlers;
  }

  toJSON() {
    return this.model._id
  }
}


export class RobotPlayerRmqProxy extends PlayerRmqProxy {

  sendMessage(name: string, message: any) {
  }

  async addGold(g) {
  }
}
